/* SPDX-License-Identifier: GPL-2.0 */
/*	Himax Android Driver Sample Code for ic core functions
 *
 *	Copyright (C) 2021 Himax Corporation.
 *
 *	This software is licensed under the terms of the GNU General Public
 *	License version 2,	as published by the Free Software Foundation,  and
 *	may be copied,	distributed,  and modified under those terms.
 *
 *	This program is distributed in the hope that it will be useful,
 *	 but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 */

#ifndef __HIMAX_IC_CORE_H__
#define __HIMAX_IC_CORE_H__

#include "himax_platform.h"
#include "himax_common.h"
#include <linux/slab.h>

#define DATA_LEN_8				8
#define DATA_LEN_4				4
#define ADDR_LEN_4				4
#define FLASH_RW_MAX_LEN		256
#define FLASH_WRITE_BURST_SZ	8
#define MAX_I2C_TRANS_SZ		128
#define HIMAX_TOUCH_DATA_SIZE	128
#define HIMAX_REG_RETRY_TIMES	5

#define FW_SECTOR_PER_BLOCK		8
#define FW_PAGE_PER_SECTOR		64
#define FW_PAGE_SZ				128
#define HX1K					0x400
#define HX64K					0x10000

#define HX_RW_REG_FAIL			(-1)
#define HX_DRIVER_MAX_IC_NUM	5

#if defined(__HIMAX_HX83191_MOD__)
#define HX_MOD_KSYM_HX83191 HX_MOD_KSYM_HX83191
#endif

#if defined(__HIMAX_HX83192_MOD__)
#define HX_MOD_KSYM_HX83192 HX_MOD_KSYM_HX83192
#endif

#if defined(__HIMAX_HX83193_MOD__)
#define HX_MOD_KSYM_HX83193 HX_MOD_KSYM_HX83193
#endif

/* CORE_INIT */
/* CORE_FW */
/* CORE_FLASH */
/* CORE_SRAM */

void himax_mcu_in_cmd_struct_free(void);

#if (HX_BOOT_UPGRADE == 0x01)
extern int g_i_FW_VER;
extern int g_i_CFG_VER;
extern int g_i_CID_MAJ;
extern int g_i_CID_MIN;
extern const struct firmware *hxfw;
#endif


#if (HX_EXCP_RECOVERY == 0x01)
extern int g_zero_event_count;
#endif

#if (HX_RST_PIN_FUNC == 0x01)
void himax_gpio_set(int pinnum, uint8_t value);
#endif

int himax_report_data_init(void);
extern int i2c_error_count;

#if (HX_EXCP_RECOVERY == 0x01)
extern u8 HX_EXCP_RESET_ACTIVATE;
#endif

/* CORE_INIT */
int himax_mcu_in_cmd_struct_init(void);
void himax_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len);
int himax_disable_flash_protected_mode(void);
int himax_enable_flash_protected_mode(void);
int himax_mcu_WP_BP_status(void);
int himax_mcu_flash_id_check(void);
int himax_mcu_register_write(uint32_t write_addr, uint32_t write_length, uint8_t *write_data);
int himax_mcu_register_read(uint32_t read_addr, uint32_t read_length, uint8_t *read_data);
void himax_mcu_tp_lcm_pin_reset(void);
void himax_mcu_burst_enable(uint8_t auto_add_4_byte);
void himax_mcu_interface_on(void);
bool himax_mcu_wait_wip(int Timing);
void himax_mcu_power_on_init(void);
bool himax_mcu_dd_reg_write(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank);
bool himax_mcu_dd_reg_read(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank);
void himax_mcu_system_reset(void);
void himax_mcu_command_reset(void);
int himax_mcu_calculate_CRC32_by_AP(unsigned char *FW_content, int CRC_from_FW, int len);
uint32_t himax_mcu_check_CRC(uint8_t *start_addr, int reload_length);
void himax_mcu_diag_register_set(uint8_t diag_command, uint8_t storage_type, bool convert_diag);
void himax_mcu_reload_disable(int disable);
void himax_mcu_rawdata_normalize_disable(int disable);
int himax_mcu_read_ic_trigger_type(void);
void himax_mcu_read_FW_ver(void);
void himax_print_define_function(void);
bool himax_mcu_read_event_stack(uint8_t *buf, uint8_t length);
void himax_mcu_stop_DSRAM_output(void);
bool himax_mcu_calculateChecksum(uint32_t size);
int himax_mcu_assign_sorting_mode(uint8_t *tmp_data);
bool himax_mcu_sector_erase(int start_addr, int length);
int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k(unsigned char *fw, int len, bool change_iref);
bool himax_mcu_flash_lastdata_check_with_bin(uint32_t size);
bool hx_mcu_bin_desc_get(unsigned char *fw, uint32_t max_sz);
bool himax_mcu_get_DSRAM_data(uint8_t *info_data, bool DSRAM_Flag);
int himax_mcu_fw_ver_bin(void);
void himax_mcu_ic_reset(uint8_t loadconfig, uint8_t int_off);
void himax_mcu_touch_information(void);
int himax_mcu_get_touch_data_size(void);
int himax_mcu_cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max);
bool himax_mcu_diag_check_sum(struct himax_report_data *hx_touch_data);
void himax_mcu_diag_parse_raw_data(struct himax_report_data *hx_touch_data,
	 int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data);
void himax_mcu_read_FW_status(void);
int himax_mcu_check_sorting_mode(uint8_t *tmp_data);
int himax_mcu_check_N_frame(uint8_t *tmp_data);
void himax_mcu_reload_config(void);
int himax_mcu_read_i2c_status(void);
struct timespec64 time_diff(struct timespec64 start, struct timespec64 end);
void himax_mcu_set_SMWP_enable(uint8_t SMWP_enable, bool suspended);
void himax_mcu_excp_ic_reset(void);
int himax_mcu_ic_excp_recovery(uint32_t hx_excp_event,
		uint32_t hx_zero_event, uint32_t length);
/* CORE_INIT */

enum AHB_Interface_Command_Table {
	addr_AHB_address_byte_0		=	0x00,
	addr_AHB_rdata_byte_0		=	0x08,
	addr_AHB_access_direction	=	0x0C,
	addr_AHB_continous			=	0x13,
	addr_AHB_INC4				=	0x0D,
	addr_sense_on_off_0			=	0x31,
	addr_sense_on_off_1			=	0x32,
	addr_read_event_stack		=	0x30,
	para_AHB_access_direction_read	=	0x00,
	para_AHB_continous			=	0x31,
	para_AHB_INC4				=	0x10,
	para_sense_off_0			=	0x27,
	para_sense_off_1			=	0x95,
};
/* CORE_FW */
	#define addr_fw_state						0x800204DC
	#define addr_psl							0x900000A0
	#define addr_cs_central_state				0x900000A8
	#define addr_flag_reset_event				0x900000E4
	#define addr_chk_dd_status					0x900000E8
	#define addr_osc_en							0x9000009C
	#define addr_osc_pw							0x90000280
	#define addr_system_reset					0x90000018
	#define addr_ctrl_fw						0x9000005C
	#define addr_icid_addr						0x900000D0
	#define addr_program_reload_from			0x00000000
	#define addr_reload_status					0x80050000
	#define addr_reload_crc32_result			0x80050018
	#define addr_reload_addr_from				0x80050020
	#define addr_reload_addr_cmd_beat			0x80050028
	#define data_system_reset					0x00000055
	#define data_clear							0x00000000
	#define addr_raw_out_sel					0x100072EC
	#define addr_set_frame_addr					0x10007294
	#define addr_sorting_mode_en				0x10007F04
	#define addr_fw_mode_status					0x10007088
	#define addr_fw_architecture_version		0x10007004
	#define addr_fw_config_date					0x10007038
	#define addr_fw_config_version				0x10007084
	#define addr_fw_CID							0x10007000
	#define addr_fw_customer					0x10007008
	#define addr_fw_project_name				0x10007014
	#define addr_fw_dbg_msg_addr				0x10007F40
	#define addr_HX_ID_EN						0x10007134
	#define addr_fw_define_flash_reload			0x10007f00
	#define addr_fw_define_rawdata_normalize	0x10007130
	#define addr_fw_define_2nd_flash_reload		0x100072c0
	#define data_fw_define_flash_reload_dis		0x0000a55a
	#define data_fw_define_flash_reload_en		0x00000000
	#define addr_fw_define_int_is_edge			0x10007088
	#define addr_fw_define_rxnum_txnum_maxpt	0x100070f4
	#define addr_fw_define_xy_res				0x100070f8
	#define addr_rawdata						0x10000000
	#define addr_fail_det_GPIO1_msg				0x100074C0
	#define addr_WDT_disable					0x9000800C
	#define addr_retry_wrapper_clr_pw			0x900002A0


	#define fw_func_handshaking_pwd				0xA55AA55A
	#define fw_data_safe_mode_release_pw_reset	0x00000000
	#define fw_addr_smwp_enable					0x10007F10


/* CORE_FLASH */
	#define addr_ctrl_base						0x80000000
	#define addr_spi200_trans_fmt				(addr_ctrl_base + 0x10)
	#define addr_spi200_trans_ctrl				(addr_ctrl_base + 0x20)
	#define addr_spi200_cmd						(addr_ctrl_base + 0x24)
	#define addr_spi200_addr					(addr_ctrl_base + 0x28)
	#define addr_spi200_data					(addr_ctrl_base + 0x2c)
	#define addr_spi200_fifo_rst				(addr_ctrl_base + 0x30)
	#define addr_spi200_rst_status				(addr_ctrl_base + 0x34)
	#define addr_spi200_flash_speed				(addr_ctrl_base + 0x40)
	#define data_spi200_txfifo_rst				0x00000004
	#define data_spi200_rxfifo_rst				0x00000002
	#define data_spi200_trans_fmt				0x00020780
	#define data_spi200_trans_ctrl_1			0x42000003
	#define data_spi200_trans_ctrl_2			0x47000000
	#define data_spi200_trans_ctrl_3			0x67000000
	#define data_spi200_trans_ctrl_4			0x610ff000
	#define data_spi200_trans_ctrl_6			0x42000000
	#define data_spi200_trans_ctrl_7			0x6940020f
	#define data_spi200_cmd_1					0x00000005
	#define data_spi200_cmd_2					0x00000006
	#define data_spi200_cmd_3					0x000000C7
	#define data_spi200_cmd_4					0x000000D8
	#define data_spi200_cmd_6					0x00000002
	#define data_spi200_cmd_7					0x0000003b
	#define data_spi200_cmd_8					0x00000003
	#define data_set_flash_speed				0x00000001
	#define addr_WP_pin_base					0x90028000
	#define addr_WP_gpio0_cmd_04				(addr_WP_pin_base + 0x04)
	#define addr_WP_gpio0_cmd_0C				(addr_WP_pin_base + 0x0C)
	#define data_WP_gpio0_cmd_00				0x00000000
	#define data_WP_gpio0_cmd_01				0x00000001
	#define addr_WP_gpio4_cmd_04				(addr_WP_pin_base + 0x04)
	#define addr_WP_gpio4_cmd_1C				(addr_WP_pin_base + 0x1C)
	#define data_WP_gpio4_cmd_00				0x00000000
	#define data_WP_gpio4_cmd_01				0x00000001
	#define data_WP_gpio4_cmd_10				0x00000010
	#define addr_BP_lock_base					0x80000000
	#define addr_BP_lock_cmd_10					(addr_BP_lock_base + 0x10)
	#define addr_BP_lock_cmd_20					(addr_BP_lock_base + 0x20)
	#define addr_BP_lock_cmd_24					(addr_BP_lock_base + 0x24)
	#define addr_BP_lock_cmd_2C					(addr_BP_lock_base + 0x2C)
	#define data_BP_lock_cmd_1					0x00020780
	#define data_BP_lock_cmd_2					0x47000000
	#define data_BP_lock_cmd_3					0x00000006
	#define data_BP_lock_cmd_4					0x41000000
	#define data_BP_lock_cmd_5					0x00000000
	#define data_BP_lock_cmd_6					0x00000001
	#define data_BP_lock_cmd_7					0x0000009C
	#define data_BP_check_cmd_1					0x42000000
	#define data_BP_check_cmd_2					0x00000005
	#define data_BP_check_cmd_3					0x42000002
	#define data_BP_check_cmd_4					0x0000009F

enum bin_desc_map_table {
	TP_CONFIG_TABLE = 0x0000000A,
	FW_CID = 0x10000000,
	FW_VER = 0x10000100,
	CFG_VER = 0x30000000,//0x10000005,
};

extern uint32_t dbg_reg_ary[4];

struct himax_core_fp {
	void (*fp_sense_on)(uint8_t FlashMode);
	bool (*fp_sense_off)(void);
	bool (*fp_dd_clk_set)(bool enable);
	void (*fp_dd_reg_en)(bool enable);
/* CORE_FLASH */
	void (*fp_flash_programming)(uint8_t *FW_content, int start_addr, int FW_Size);
	void (*fp_flash_dump_func)(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
/* CORE_FLASH */
};

#endif

#define Flash_list {{0xEF, 0x30, 0x12}, {0xEF, 0x60, 0x12}, {0xC8, 0x60, 0x13}, \
					{0xC8, 0x60, 0x12}, {0xC2, 0x28, 0x11}, {0xC2, 0x28, 0x12}, \
					{0xC2, 0x25, 0x32}, {0x85, 0x60, 0x13}, {0x85, 0x60, 0x12}, \
					{0x85, 0x40, 0x12}, {0x7F, 0x11, 0x52}, {0x5E, 0x60, 0x13}, \
					{0x1C, 0x38, 0x13}, {0x1C, 0x38, 0x12}, {0x9D, 0x40, 0x12}, \
					{0x9D, 0x60, 0x15}}


